﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Media3D;
using _3DTools;
using System.Windows.Input;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Diagnostics;
using System.Collections;
using System.IO;
using Data;
namespace DCSElab_Project
{


    public class Utility
    {




        public int bien = 0;
        public int Transform
        {
            get { return bien; }
        }
        /// <summary>
        /// cai dat vi tri camera de quan sat nhieu doi tuong
        /// </summary>
        /// <param name="cam">Loai camera OrthographicCamera</param>
        /// <param name="group">Danh sach cac doi tuong</param>
        public static void SetCamera(OrthographicCamera cam, Data.Model3D group)
        {
            Point3D center = new Point3D();
            center = group.GetCenter();
            Double zmax = 0;
            zmax = group.Zmax();
            cam.Position = camera_position(center, zmax, 500);
            cam.Width = Width(group.Xmax(), group.Xmin());
        }
        public static void SetCamera(OrthographicCamera cam, List<Point3D> list_point)
        {
            Point3D center = new Point3D();
            center = GetModelCenter(list_point);
            Double zmax = 0;
            zmax = GetZ_Max(list_point);
            cam.Position = camera_position(center, zmax, 500);
            cam.Width = Width(GetX_Max(list_point), GetX_Min(list_point));
        }
        /// <summary>
        /// Xac dinh vi tri cho camera
        /// </summary>
        /// <param name="a">vi tri trung tam cac doi tuong</param>
        /// <param name="max_z">Gia tri Z lon nhat</param>
        /// <param name="r">Khoang cach tu camera toi vat</param>
        /// <returns></returns>
        public static Point3D camera_position(Point3D a, Double max_z, Double r)
        {
            Point3D B = new Point3D(0, 0, 0);
            B.X = a.X;
            B.Y = a.Y;
            B.Z = r + a.Z + max_z;// Vi tri camera dat cach xa vat mot khoang r

            return B;
        }
        /// <summary>
        /// Tinh khoang cach hai so
        /// </summary>
        /// <param name="min">gia tri min </param>
        /// <param name="max">gia tri max</param>
        /// <returns>double</returns>
        public static Double Width(Double min, Double max)
        {
            return (Math.Abs(min) + Math.Abs(max)) * 2.5;
        }

        /// <summary>
        /// Xac dinh trong tam cua vat
        /// </summary>
        /// <param name="array">Danh sach diem</param>
        /// <returns>loai Point3D</returns>
        public static Point3D GetModelCenter(ArrayList array)
        {
            Point3D center = new Point3D(0, 0, 0);
            Point3D temp = new Point3D(0, 0, 0);
            int i = array.Count;
            Double sumx, sumy, sumz;

            sumz = sumy = sumx = 0;
            while (i > 0)
            {
                temp = (Point3D)array[i - 1];
                sumx = sumx + temp.X;
                sumy = sumy + temp.Y;
                sumz = sumz + temp.Z;
                i--;
            }

            center.X = Math.Round(sumx / array.Count);
            center.Y = Math.Round(sumy / array.Count);
            center.Z = Math.Round(sumz / array.Count);
            return center;
        }
        /// <summary>
        /// Xac dinh trong tam cua vat
        /// </summary>
        /// <param name="array">Danh sach diem</param>
        /// <returns>loai Point3D</returns>
        public static Point3D GetModelCenter(List<Point3D> array)
        {
            Point3D center = new Point3D(0, 0, 0);
            Point3D temp = new Point3D(0, 0, 0);
            int i = array.Count;
            Double sumx, sumy, sumz;

            sumz = sumy = sumx = 0;
            while (i > 0)
            {
                temp = (Point3D)array[i - 1];
                sumx = sumx + temp.X;
                sumy = sumy + temp.Y;
                sumz = sumz + temp.Z;
                i--;
            }

            center.X = Math.Round(sumx / array.Count);
            center.Y = Math.Round(sumy / array.Count);
            center.Z = Math.Round(sumz / array.Count);
            return center;
        }

        /// <summary>
        /// Tim gia tri Z lon nhat trong danh sach diem
        /// </summary>
        /// <param name="array">Danh sach diem</param>
        /// <returns>double</returns>
        public static Double GetZ_Max(ArrayList array)
        {
            Double temp;
            Point3D orin = (Point3D)array[0];
            temp = orin.Z;
            for (int i = 0; i < array.Count; i++)
            {
                Point3D dem = (Point3D)array[i];
                if (temp < dem.Z)
                    temp = dem.Z;
            }
            return temp;
        }
        /// <summary>
        /// Tim gia tri Z lon nhat trong danh sach diem
        /// </summary>
        /// <param name="array">Danh sach diem</param>
        /// <returns>double</returns>
        public static Double GetZ_Max(List<Point3D> array)
        {
            Double temp;
            Point3D orin = (Point3D)array[0];
            temp = orin.Z;
            for (int i = 0; i < array.Count; i++)
            {
                Point3D dem = (Point3D)array[i];
                if (temp < dem.Z)
                    temp = dem.Z;
            }
            return temp;
        }
        /// <summary>
        /// Tim gia tri z nho nhat trong danh sach diem
        /// </summary>
        /// <param name="a"></param>
        /// <returns>double</returns>
        public static Double Get_Z_Min(ArrayList a)
        {
            Double temp;
            Point3D orin = (Point3D)a[0];
            temp = orin.Z;
            for (int i = 0; i < a.Count; i++)
            {
                Point3D dem = (Point3D)a[i];
                if (temp > dem.Z)
                    temp = dem.Z;
            }
            return temp;
        }
        /// <summary>
        /// Tim gia tri z nho nhat trong danh sach diem
        /// </summary>
        /// <param name="a">Danh sach diem</param>
        /// <returns>double</returns>
        public static Double GetZ_Min(List<Point3D> a)
        {
            Double temp;
            Point3D orin = (Point3D)a[0];
            temp = orin.Z;
            for (int i = 0; i < a.Count; i++)
            {
                Point3D dem = (Point3D)a[i];
                if (temp > dem.Z)
                    temp = dem.Z;
            }
            return temp;
        }

        /// <summary>
        /// Tim gia tri x nho nhat trong danh sach diem
        /// </summary>
        /// <param name="a">danh sach diem</param>
        /// <returns></returns>
        public static Double Get_X_Min(ArrayList a)
        {
            Double temp;
            Point3D orin = (Point3D)a[0];
            temp = orin.X;
            for (int i = 0; i < a.Count; i++)
            {
                Point3D dem = (Point3D)a[i];
                if (temp > dem.X)
                    temp = dem.X;
            }
            return temp;
        }

        /// <summary>
        /// Tim gia tri x nho nhat trong danh sach diem
        /// </summary>
        /// <param name="a">danh sach diem</param>
        /// <returns></returns>
        public static Double GetX_Min(List<Point3D> a)
        {
            Double temp;
            Point3D orin = (Point3D)a[0];
            temp = orin.X;
            for (int i = 0; i < a.Count; i++)
            {
                Point3D dem = (Point3D)a[i];
                if (temp > dem.X)
                    temp = dem.X;
            }
            return temp;
        }
        /// <summary>
        /// tim gia tri x lon nhat trong danh sach diem
        /// </summary>
        /// <param name="a">danh sach diem</param>
        /// <returns>double</returns>
        public static Double GetX_Max(ArrayList a)
        {
            Double temp;
            Point3D orin = (Point3D)a[0];
            temp = orin.X;
            for (int i = 0; i < a.Count; i++)
            {
                Point3D dem = (Point3D)a[i];
                if (temp < dem.X)
                    temp = dem.X;
            }
            return temp;
        }
        /// <summary>
        /// tim gia tri x lon nhat trong danh sach diem
        /// </summary>
        /// <param name="a">danh sach diem</param>
        /// <returns>double</returns>
        public static Double GetX_Max(List<Point3D> a)
        {
            Double temp;
            Point3D orin = (Point3D)a[0];
            temp = orin.X;
            for (int i = 0; i < a.Count; i++)
            {
                Point3D dem = (Point3D)a[i];
                if (temp < dem.X)
                    temp = dem.X;
            }
            return temp;
        }

        public static int find_point(ArrayList a, Point3D x)
        {
            int i = a.BinarySearch(x);

            return i;
        }
        // Phuong thuc kiem tra diem co thuoc khong gian hien thi.
        public static bool check(Point3D input, Point3D threshold, Double value)
        {
            Double validx = Math.Abs(input.X - threshold.X);
            Double validy = Math.Abs(input.Y - threshold.Y);
            value = value / 2 - 1;
            if (validx <= value && validy <= value)
                return true;
            return false;
        }
        // Phuong thuc xac dinh toa do diem 2D tu toa do 3D
        public static Point find_2d(Point3D point3d, Viewport3D main_viewport)
        {
            bool bOK = false;
            Point screen2d = new Point(0, 0);
            Viewport3DVisual vpv = VisualTreeHelper.GetParent(main_viewport.Children[0]) as Viewport3DVisual;
            Matrix3D m = MathUtils.TryWorldToViewportTransform(vpv, out bOK);
            if (bOK)
            {
                Point3D transformedPoint = m.Transform(point3d);
                screen2d = new Point(transformedPoint.X, transformedPoint.Y);
                screen2d.X = Math.Round(screen2d.X, 2);
                screen2d.Y = Math.Round(screen2d.Y, 2);
            }

            return screen2d;

        }
        // Phuong thuc ve 3 truc toa do
        public static void draw_axis(ModelVisual3D disp, Point3D p)
        {
            ScreenSpaceLines3D ss1 = new ScreenSpaceLines3D();
            ss1.Points.Add(new Point3D(p.X, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X + 5, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y + 5, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y, 5));
            ss1.Color = Colors.Black;
            ss1.Thickness = 1;
            //return ss1;
            disp.Children.Add(ss1);
        }
        // Phuong thuc xac dinh goc tao do cua ba truc minh hoa.
        public static Point3D find_axis_ori(Point3D p, Double r)
        {
            Point3D origin = new Point3D();
            origin.X = p.X - r / 2 + 5;
            origin.Y = p.Y - r / 2 + 5;
            origin.Z = 0;
            return origin;
        }
        //Nhom cac phuong thuc chuyen doi toa do sang he toa do moi thong qua 3 diem
        public static Point3D UCS(Point3D value, Point3D O, Point3D X, Point3D Y)
        {
            Point3D PNEW;
            Vector3D PX, PY, PZ, valid, valid1;
            PZ = normal_vector(O, X, Y);// Oz axis of UCS 
            PX = new Vector3D(X.X - O.X, X.Y - O.Y, X.Z - O.Z);// Ox axis of UCS
            PY = Vector3D.CrossProduct(PX, PZ);// Oy axis of UCS
            valid1 = Vector3D.CrossProduct(PX, PY);// Check if points are valid
            valid = Vector3D.CrossProduct(valid1, PZ);//
            if (valid1 != new Vector3D(0, 0, 0))
            {

                PX.Normalize();
                PY.Normalize();
                PZ.Normalize();
                Double x1 = value.X - O.X;
                Double y1 = value.Y - O.Y;
                Double z1 = value.Z - O.Z;
                Double x = Math.Round(PX.X * x1 + PX.Y * y1 + PX.Z * z1, 2);
                Double y = Math.Round(PY.X * x1 + PY.Y * y1 + PY.Z * z1, 2);
                Double z = Math.Round(PZ.X * x1 + PZ.Y * y1 + PZ.Z * z1, 2);
                PNEW = new Point3D(x, y, z);
            }
            else
            {
                //MessageBox.Show("Points are not valid, please choose others");
                PNEW = value;
            }
            return PNEW;
        }
        public static Vector3D normal_vector(Point3D O, Point3D X, Point3D Y)
        {
            Vector3D n;
            Vector3D ox = new Vector3D(X.X - O.X, X.Y - O.Y, X.Z - O.Z);
            Vector3D oy = new Vector3D(Y.X - O.X, Y.Y - O.Y, Y.Z - O.Z);
            n = Vector3D.CrossProduct(ox, oy);
            return n;
        }
        //tim vector phap tuyen cua 1 mp

        //khoang cach tu diem den mp
        public static Double distance_from_point_to_plane(Vector3D P1, Point3D P2, Point3D P3)
        {
            Double d;
            Double dd = -(P1.X * P2.X + P1.Y * P2.Y + P1.Z * P2.Z);

            d = System.Math.Abs(P1.X * P3.X + P1.Y * P3.Y + P1.Z * P3.Z + dd) / System.Math.Sqrt(P1.X * P1.X + P1.Y * P1.Y + P1.Z * P1.Z);

            return d;
        }
        public static bool Check_ScanPlanes(Point3D point, int number_planes, Point3D point_1, Point3D point_2, Point3D point_3, Point3D point_stop)
        {
            Vector3D PT;
            PT = normal_vector(point_1, point_2, point_3);
            bool f_planes = false;
            Double dis_pointstop_to_plane = DCSElab_Project.Utility.distance_from_point_to_plane(PT, point_3, point_stop);
            dis_pointstop_to_plane = dis_pointstop_to_plane / number_planes;
            // kiem tra co cung phia voi point_stop hay khong
            Double sign = (PT.X * (point_3.X - point_stop.X) + PT.Y * (point_3.Y - point_stop.Y) + PT.Z * (point_3.Z - point_stop.Z)) * (PT.X * (point_3.X - point.X) + PT.Y * (point_3.Y - point.Y) + PT.Z * (point_3.Z - point.Z));
            if (sign >= 0)
            {
                Double dis_point_to_plane = DCSElab_Project.Utility.distance_from_point_to_plane(PT, point_3, point);
                for (int l = 1; l <= number_planes; l++)
                {
                    Double temp2 = dis_pointstop_to_plane * l;
                    if (System.Math.Abs(temp2 - dis_point_to_plane) >= 0.1)
                    {
                        f_planes = true;
                    }
                    else
                    {
                        f_planes = false;
                    }
                }
            }
            if (f_planes == true) return true;
            else return false;
        }
        // Khoang cach giua hai diem
        public static Double dis(Point3D p1, Point3D p2)
        {
            return System.Math.Round(System.Math.Sqrt(System.Math.Pow(p1.X - p2.X, 2) + System.Math.Pow(p1.Y - p2.Y, 2) + System.Math.Pow(p1.Z - p2.Z, 2)), 2);
        }


        public static string ChuanHoa(string s1)
        {
            string s = s1.Trim(); // Xóa khoảng trắng đầu và cuối     

            int space = 0;
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == ' ')
                    space++; // Tim duoc space     
                else
                    space = 0; // Quay lai 1 tu moi khi ket thuc space     
                if (space > 1)
                {
                    space = 0;
                    do
                    {
                        if (s[i] == ' ')
                            s = s.Remove(i, 1);
                    } while (s[i] == ' ');
                }
            }

            return s;


        }
        public static ScreenSpaceLines3D draw_axis_line(Point3D p)
        {

            ScreenSpaceLines3D ss1 = new ScreenSpaceLines3D();
            ss1.Points.Add(new Point3D(p.X, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X + 5, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y + 5, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y, 0));
            ss1.Points.Add(new Point3D(p.X, p.Y, 5));
            ss1.Color = Colors.Crimson;
            ss1.Thickness = 3;
            return ss1;
        }

        public static Model3DGroup read_file(string file)
        {
            // for display object
            ///////////////////////////////////////////
            Model3DGroup solid = new Model3DGroup();
            ArrayList mesh = new ArrayList();
            GeometryModel3D geometry = new GeometryModel3D();
            SolidColorBrush brush = new SolidColorBrush();
            brush.Color = Colors.Red;
            Material material = new DiffuseMaterial(brush);
            MeshGeometry3D facet = new MeshGeometry3D();
            geometry.Material = material;



            //////////////////////////////////////////
            int i = 0;
            int dem = 0;
            string s, s1;
            string[] separators = new string[] { " ", "," };
            StreamReader re = System.IO.File.OpenText(file);
            Vector3D normal = new Vector3D();
            Point3D v1 = new Point3D();
            Point3D v2 = new Point3D();
            Point3D v3 = new Point3D();
            DateTime start_time = DateTime.Now;
            while ((s1 = re.ReadLine()) != null)
            {
                s = s1.Trim();
                s.ToLower();
                s = DCSElab_Project.Utility.ChuanHoa(s);
                string[] line;

                if (s.StartsWith("solid"))
                {
                    //do anything
                }

                else if (s.StartsWith("facet"))// gap tu khoa facet thi xac dinh dinh cua phap vecto
                {

                    string[] slipt = s.Split(new Char[] { ' ' });

                    normal = new Vector3D(float.Parse(slipt[2]), float.Parse(slipt[3]), float.Parse(slipt[4]));

                }

                else if (s.StartsWith("vertex"))
                {
                    // parse: vertex x y z  
                    if (dem == 0)
                    {
                        line = s.Split(' ');

                        v1 = new Point3D(float.Parse(line[1]), float.Parse(line[2]), float.Parse(line[3]));
                        dem++;
                    }
                    else if (dem == 1)
                    {
                        line = s.Split(' ');

                        v2 = new Point3D(float.Parse(line[1]), float.Parse(line[2]), float.Parse(line[3]));
                        dem++;
                    }
                    else
                    {
                        line = s.Split(' ');
                        v3 = new Point3D(float.Parse(line[1]), float.Parse(line[2]), float.Parse(line[3]));
                        dem = 0;
                    }
                }
                else if (s == "endfacet")
                {


                    facet.Positions.Add(v1);
                    facet.Positions.Add(v2);
                    facet.Positions.Add(v3);
                    facet.TriangleIndices.Add(0 + 3 * i);
                    facet.TriangleIndices.Add(1 + 3 * i);
                    facet.TriangleIndices.Add(2 + 3 * i);
                    facet.Normals.Add(normal);
                    facet.Normals.Add(normal);
                    facet.Normals.Add(normal);
                    mesh.Add(v1);
                    mesh.Add(v2);
                    mesh.Add(v2);
                    i++;


                }
                else if (s.StartsWith("endsolid"))
                {

                    geometry.Geometry = facet;
                    solid.Children.Add(geometry);
                }


            }
            re.Close();
            return solid;
        }
        public static Model3DGroup Text3D(string text, Brush textColor, Double height, Point3D center, Vector3D over, Vector3D up)
        {
            // First we need a textblock containing the text of our label
            TextBlock tb = new TextBlock(new System.Windows.Documents.Run(text));
            tb.Foreground = textColor;
            tb.FontFamily = new FontFamily("Arial");

            // Now use that TextBlock as the brush for a material
            DiffuseMaterial mat = new DiffuseMaterial();
            mat.Brush = new VisualBrush(tb);

            // We just assume the characters are square
            Double width = text.Length * height;

            // Since the parameter coming in was the center of the label,
            // we need to find the four corners
            // p0 is the lower left corner
            // p1 is the upper left
            // p2 is the lower right
            // p3 is the upper right
            Point3D p0 = center - width / 2 * over - height / 2 * up;
            Point3D p1 = p0 + up * 1 * height;
            Point3D p2 = p0 + over * width;
            Point3D p3 = p0 + up * 1 * height + over * width;

            // Now build the geometry for the sign.  It's just a
            // rectangle made of two triangles, on each side.

            MeshGeometry3D mg = new MeshGeometry3D();
            mg.Positions = new Point3DCollection();
            mg.Positions.Add(p0);    // 0
            mg.Positions.Add(p1);    // 1
            mg.Positions.Add(p2);    // 2
            mg.Positions.Add(p3);    // 3



            mg.Positions.Add(p0);    // 4
            mg.Positions.Add(p1);    // 5
            mg.Positions.Add(p2);    // 6
            mg.Positions.Add(p3);    // 7


            mg.TriangleIndices.Add(0);
            mg.TriangleIndices.Add(3);
            mg.TriangleIndices.Add(1);
            mg.TriangleIndices.Add(0);
            mg.TriangleIndices.Add(2);
            mg.TriangleIndices.Add(3);

            mg.TriangleIndices.Add(4);
            mg.TriangleIndices.Add(5);
            mg.TriangleIndices.Add(7);
            mg.TriangleIndices.Add(4);
            mg.TriangleIndices.Add(7);
            mg.TriangleIndices.Add(6);


            // These texture coordinates basically stretch the
            // TextBox brush to cover the full side of the label.

            mg.TextureCoordinates.Add(new Point(0, 1));
            mg.TextureCoordinates.Add(new Point(0, 0));
            mg.TextureCoordinates.Add(new Point(1, 1));
            mg.TextureCoordinates.Add(new Point(1, 0));



            mg.TextureCoordinates.Add(new Point(1, 1));
            mg.TextureCoordinates.Add(new Point(1, 0));
            mg.TextureCoordinates.Add(new Point(0, 1));
            mg.TextureCoordinates.Add(new Point(0, 0));


            // And that's all.  Return the result.

            Model3DGroup mgroup = new Model3DGroup();
            mgroup.Children.Add(new GeometryModel3D(mg, mat));
            return mgroup;

        }

        public static Model3DGroup Text_Axis()
        {
            Model3DGroup a = new Model3DGroup();
            a.Children.Add(Text3D("X", Brushes.Red, 0.5, new Point3D(2, -0.5, 0), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)));
            a.Children.Add(Text3D("Y", Brushes.Red, 0.5, new Point3D(0.5, 2, 0), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)));
            a.Children.Add(Text3D("Z", Brushes.Red, 0.5, new Point3D(0.5, 0, 2), new Vector3D(1, 0, 0), new Vector3D(0, 1, 0)));
            return a;
        }
        public static GeometryModel3D create_geometry(Color color, MeshGeometry3D mesh)
        {
            GeometryModel3D geometry = new GeometryModel3D();
            SolidColorBrush brush = new SolidColorBrush();
            brush.Color = color;
            Material material = new DiffuseMaterial(brush);
            geometry.Geometry = mesh;
            geometry.Material = material;
            return geometry;

        }
        ///////////////////////////////////////////////////////////////////////////////////////////
        // Nhom phuong thuc hien thi doi tuong cat
        /////////////////////////////////////////////////////////////////////////////////////////

        public static ModelVisual3D CreateLine(List<Point3D> point_list, Color color)
        {
            ScreenSpaceLines3D line = new ScreenSpaceLines3D();
            for (int i = 0; i < point_list.Count; i++)
            {
                line.Points.Add(point_list[i]);
            }
            line.Color = color;
            line.Thickness = 1;
            return line;
        }
        /// <summary>
        /// Hien thi doi tuong cat
        /// </summary>
        /// <param name="point_list">Danh sach cac diem thuoc doi tuong cat</param>
        /// <param name="dz">Do day lop cat</param>
        /// <param name="color">Mau sac hien thi</param>
        /// <returns>danh sach ModelVisual3D</returns>
        public static List<ModelVisual3D> CreateListModelVisual3D(List<Point3D> point_list, double dz, Color color)
        {
            /*Do sanh sach duoc xap xep tang dan theo Z vi the chung ta chi can duyet theo tung gia tri z
             Chung ta co 3 loai danh sach diem
             *Danh sach diem cua cac doi tuong cat(chi bao gom diem thuoc doi tuong cat khong co diem thuoc luoi)
             *Danh sach diem tung mat cat(theo tung gia tri Z)
             *Danh sach diem theo moi contour kin tai tung gia tri Z
            */

            List<ModelVisual3D> _listModelVisual = new List<ModelVisual3D>();// danh sach cac doi tuong ModeLVisual3D
            //Moi thanh phan duoc tao ra tu moi contour kin  
            ScreenSpaceLines3D _polyLine = new ScreenSpaceLines3D();      //Doi tuong polyline duoc dung de noi cac diem thuoc contou kin

            List<Point3D> _contour = new List<Point3D>(); //Danh sach diem moi contour kin
            List<Point3D> _pointList = point_list;// su dung danh sach temp de luu tru roi xu li cac diem trong point_list
            double zMin = GetZ_Min(_pointList);
            double zMax = GetZ_Max(_pointList);

            int pos_dz = 0; // bien luu gia tri bat dau cho mot danh sach diem theo tung gia tri z
            List<Point3D> _tempList = new List<Point3D>();// danh sach diem cho tung mat cat(co the bao gom nhieu contour)

            int pos = 1;// bien luu vi tri bat dau moi contour trong danh sach diem theo tung gia tri z
            double dz_inc = 0;
            int j = 0, i = 0;
            Point3D temp, first;//temp -> Contour ,first ->  danh sach diem cac doi tuong


            for (dz_inc = zMin; dz_inc <= zMax; dz_inc += dz) // duyet danh sach diem theo tung gia tri z
            {

                first = _pointList[pos_dz];

                for (int ii = pos_dz; ii < _pointList.Count - 1; ii++)// duyet het danh sach diem trong point_list
                {
                    if (first.Z != dz_inc)// neu gap diem nam ngoai mat cat(gia tri z khac mot Z tai tung mat cat)
                    {
                        pos_dz = ii + 1;//cai dat diem bat dau
                        // thuc hien tao doi tuong ModelVisual3D cho mat cat

                        temp = _tempList[pos];
                        for (i = pos; i < _tempList.Count - 1; i++) // duyet danh sach de lay diem thuoc contour kin
                        {
                            if (temp == _tempList[i])// phat hien diem ket thuc contour, tao doi tuong Modelvisual3D tu contour
                            {
                                _polyLine = new ScreenSpaceLines3D(); // khoi tao doi tuong polyline
                                for (j = 0; j < _contour.Count; j++)
                                {
                                    _polyLine.Points.Add(_contour[j]);
                                }
                                _polyLine.Thickness = dz / 2;
                                _polyLine.Color = color;
                                _listModelVisual.Add(_polyLine);

                                _contour.Clear();// xoa danh sach diem contour,de nhap diem moi
                                temp = _tempList[i + 1];
                                pos = i + 1;// bat dau duyet tu vi tri nay
                            }
                            else // khi chua gap diem ket thuc contour
                            {
                                _contour.Add(_pointList[i]); // them vao danh sach diem thuoc contour
                            }
                        }
                        // sau khi tao xong xoa danh sach de nhap diem moi
                        _tempList.Clear();
                    }
                    else
                    {
                        _tempList.Add(_pointList[ii]);

                    }
                }


            }

            return _listModelVisual;
        }

        public static List<ModelVisual3D> CreateListModelVisual3DComPlex(List<Point3D> pointListModel, double dz, Color color)
        {
            // contour kin thi diem dau va diem cuoi trung nhau
            /*Do sanh sach duoc xap xep tang dan theo Z vi the chung ta chi can duyet theo tung gia tri z
             Chung ta co 3 loai danh sach diem
             *Danh sach diem cua cac doi tuong cat(chi bao gom diem thuoc doi tuong cat khong co diem thuoc luoi)
             *Danh sach diem tung mat cat(theo tung gia tri Z)
             *Danh sach diem theo moi contour kin tai tung gia tri Z
            */

            List<ModelVisual3D> listModelVisual = new List<ModelVisual3D>();// danh sach cac doi tuong ModeLVisual3D
            //Moi thanh phan duoc tao ra tu moi contour kin  
            ScreenSpaceLines3D polyLine = new ScreenSpaceLines3D();      //Doi tuong polyline duoc dung de noi cac diem thuoc contour kin

            List<Point3D> contourAtZ = new List<Point3D>(); //Danh sach diem moi contour kin
            List<Point3D> allPointList = pointListModel;// su dung danh sach temp de luu tru roi xu li cac diem trong point_list
            double zMin = GetZ_Min(allPointList);
            double zMax = GetZ_Max(allPointList);
            Debug.WriteLine(string.Format("[Display sclied Model]X-Max = {0}, Z-Min = {1}", zMin,zMax));
    
            List<Point3D> tempListAtZ = new List<Point3D>();// danh sach diem cho tung mat cat(co the bao gom nhieu contour)

            int pos = 1;// bien luu vi tri bat dau moi contour trong danh sach diem theo tung gia tri z
            double dzIncrement = 0;
            int j = 0, i = 0;
            Point3D startPoint=new Point3D();//temp -> Contour ,first ->  danh sach diem cac doi tuong
            int count = 0;
            for (dzIncrement = zMin; dzIncrement <= zMax; dzIncrement += dz) // duyet danh sach diem theo tung gia tri z
            {
                Debug.WriteLine("[Display sclied model]Begin new slice");
                tempListAtZ = GetListPointOfContourAtZ(allPointList, dzIncrement);// lay danh sach tai tung gia tri z
                Debug.WriteLine("[Display sclied model]At Z = {0} tempListAtZ = {1} points", dzIncrement,tempListAtZ.Count);
                if (tempListAtZ.Count > 0)
                {
                    startPoint = tempListAtZ[0];
                    Debug.WriteLine(string.Format("[Display sclied model]Gan startPoint diem dau tien la diem dau danh sach X = {0} Y = {1}",  startPoint.X, startPoint.Y));
                    contourAtZ.Add(startPoint);// them diem dau tien vao danh sach diem cua contour
                    for (i = 1; i < tempListAtZ.Count; i++) // duyet danh sach de lay diem thuoc contour kin
                    {

                        if (startPoint.X == tempListAtZ[i].X && startPoint.Y == tempListAtZ[i].Y)// phat hien diem ket thuc contour, tao doi tuong Modelvisual3D tu contour
                        {
                            Debug.WriteLine(string.Format("[Display sclied model]Phat hien diem ket thuc contour tai i = {0} X = {1} Y = {2}",i,startPoint.X,startPoint.Y));
                            polyLine = new ScreenSpaceLines3D(); // khoi tao doi tuong polyline
                            contourAtZ.Add(tempListAtZ[i]);
                            
                            if (contourAtZ.Count > 0)
                            {
                                polyLine.Points.Add(contourAtZ[0]);
                                for (j = 1; j < contourAtZ.Count; j++)
                                {
                                    polyLine.Points.Add(contourAtZ[j]);
                                    polyLine.Points.Add(contourAtZ[j]);
                                }
                                polyLine.Thickness = dz / 2;
                                polyLine.Color = color;
                                listModelVisual.Add(polyLine);
                            }
                            contourAtZ.Clear();// xoa danh sach diem contour,de nhap diem moi
                            if (i < tempListAtZ.Count - 1)
                            {
                                i += 1; // tang i len 2 vi tri
                                startPoint = tempListAtZ[i];
                                Debug.WriteLine(string.Format("[Display sclied model]Gan startPoint diem la diem tiep theo X = {0} Y = {1} i = {2}", startPoint.X, startPoint.Y, i));
                               
                            }
                            count++;
                         
                        }
                        else if (startPoint.X != tempListAtZ[i].X || startPoint.Y != tempListAtZ[i].Y) // khi chua gap diem ket thuc contour
                        {
                            contourAtZ.Add(tempListAtZ[i]); // them vao danh sach diem thuoc contour


                        }
                        if (i == tempListAtZ.Count - 1) // khi chay toi diem cuoi cua danh sach ma khong tim thay diem dong contour
                        {
                            Debug.WriteLine(string.Format("[Display sclied model]Duyet het danh sach tai i = {0} ",i));
                            if (contourAtZ.Count > 0)
                            {
                                polyLine = new ScreenSpaceLines3D(); // khoi tao doi tuong polyline
                                contourAtZ.Add(tempListAtZ[i]);
                                if (contourAtZ.Count > 0)
                                {
                                    polyLine.Points.Add(contourAtZ[0]);
                                    for (j = 1; j < contourAtZ.Count; j++)
                                    {
                                        polyLine.Points.Add(contourAtZ[j]);
                                        polyLine.Points.Add(contourAtZ[j]);
                                    }
                                    polyLine.Thickness = dz / 2;
                                    polyLine.Color = color;
                                    listModelVisual.Add(polyLine);
                                }
                                contourAtZ.Clear();// xoa danh sach diem contour,de nhap diem moi

                            }
                        }

                    }
                    tempListAtZ.Clear();// xoa danh sach diem theo tung z

                }
            }// ket thuc duyet theo tung gia tri Z

            return listModelVisual;
        }

        /// <summary>
        /// lay danh sach diem tren courtour theo Z
        /// </summary>
        /// <param name="z">Gia tri Z can lay</param>
        /// <returns>Danh sach diem theo Z</returns>

        public static List<Point3D> GetListPointOfContourAtZ(List<Point3D> list_point, double z)
        {
            List<Point3D> _result = new List<Point3D>();
            for (int i = 0; i < list_point.Count; i++)
            {
                if (list_point[i].Z == z)
                    _result.Add(list_point[i]);
            }
            return _result;
        }

    }




}
